package com.example.demo;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang.StringUtils;

import java.io.UnsupportedEncodingException;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;

public class SHA256RSA {
    public static final String strPk = "-----BEGIN PUBLIC KEY-----\n" +
            "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAqRtw1DrB+TUScewtAW0vd/3m\n" +
            "dS+R3I2XuZk7GjOd60BkPGh+Zz1w5ba14F3hHO71YtiE3IX1SKMpos/18qM5wFlm\n" +
            "JmtDyMcMpF+HmEPKhByro9mO1qdRMg6Dl6kpizZ2hS5q4MGllty0SmiNwZQTbXVh\n" +
            "IcW1GN9Sgk3T5ioX4wIDAQAB\n" +
            "-----END PUBLIC KEY-----\n" +
            "\n";



    private static final String pkcs8PrivateKey = "-----BEGIN PRIVATE KEY-----\n" +
            "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMCpG3DUOsH5NRJx\n" +
            "7C0BbS93/eZ1L5HcjZe5mTsaM53rQGQ8aH5nPXDltrXgXeEc7vVi2ITchfVIoymi\n" +
            "z/XyoznAWWYma0PIxwykX4eYQ8qEHKuj2Y7Wp1EyDoOXqSmLNnaFLmrgwaWW3LRK\n" +
            "aI3BlBNtdWEhxbUY31KCTdPmKhfjAgMBAAECgYEAnjQ/TE96UH6LjjHudqaNOkWW\n" +
            "QQBJp8UsoELQCTBi4nKj1aulQucUFPkNKByt+oT/1JDuq2tKtTiIg1Am5Rfx37KU\n" +
            "jMfsI1uY21V7BcnLIbYf39M3RcgtszhBl28i5iulGAHGgbT1cU/KElnM55yB5RCi\n" +
            "awo46ey/wyyb4tkPqcECQQD9rAyRbNz6t6yiaSOTi3AIgwZoMxRSTcT2W++aA6s3\n" +
            "zy1DoUQ0oF0rv5sfPPs4PHe7qy/Mm/xIfVAOyKLB6I6fAkEAwm25WL9T7jwr6t7b\n" +
            "Vn9Km48wna+Rsgm6offXO0kRuNgah3dxW+mxH13vU72y/b9Dny7ezlnrLDP2cWTF\n" +
            "a7ZkPQJAXykQmelVyHPovhBk+S+AuqC0YZhv0iQ8dBKvAn7H1yrQFyPDG17hNM0v\n" +
            "GvvcXg9I90zTpJULggIIa1NWwxlDjwJAPzSeUWx5Y3QqLsNd+IOPBH0LJ+fgbElf\n" +
            "Y7IHRR2e5kFSdoFs151j2DeYStfbbUQVPpVlFx4CJq+JyRkiWL7FXQJBAK0LOdMD\n" +
            "UEQipakxizAN5TdWxMSMbjwyimBqQl6hSpaDW6wLONXjHm0pZU2oA8zu9jAvTqBV\n" +
            "En3zJ2UAJabcG5s=\n" +
            "-----END PRIVATE KEY-----\n" +
            "\n";



    public static void main(String[] args) throws Exception{

        jwttest1();

    }



    static void jwttest1() throws Exception{

        SimpleDateFormat sdf =   new SimpleDateFormat(" yyyy-MM-dd HH:mm:ss ");

        String compactJws = Jwts.builder()

                .setHeaderParam("typ", "JWT")
                .setIssuedAt(new Date())
                //.setHeaderParam("alg", "RS256") //有或者没有,都能成功,
                // 调用signWith(SignatureAlgorithm.RS256,key)的时候,会自检header签名内容,如没有会自动添加上.此行,可去掉.
                .setIssuer("1GdktdXlNZg066rrEByD5CfyzyoHQTj5")
//                .setHeaderParam("digest",)
                .setSubject("SHA-256="+SHA256("{}"))
                //.setExpiration(sdf.parse( " 2017-09-18 19:20:00 "))
                //.signWith(SignatureAlgorithm.RS256, getPrivateKey(strPk))  //test result: success.
                .signWith(SignatureAlgorithm.RS256, getPKCS8PrivateKey(pkcs8PrivateKey)) //test result: success.

                .compact();
        System.out.println(compactJws);
    }

    public static String SHA256(String param) {
        if (StringUtils.isBlank(param)) {
            throw new IllegalArgumentException("param can not be null");
        }
        try {
            byte[] bytes = param.getBytes("utf-8");
            final MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.reset();
            md.update(bytes);
            return new String(Base64.getEncoder().encode(md.digest()));
        } catch (final NoSuchAlgorithmException e) {
            throw new IllegalArgumentException("unknown algorithm SHA-256");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }



    /**

     * @param strPk RSA PRIVATE key

     * test result: success

     * */

    private static PrivateKey getPrivateKey(String strPk) throws Exception {

        // Remove markers and new line characters in private key

        String realPK = strPk.replaceAll("-----END RSA PRIVATE KEY-----", "")

                .replaceAll("-----BEGIN RSA PRIVATE KEY-----", "")

                .replaceAll("\n", "");



        byte[] b1 = Base64.getDecoder().decode(realPK);

        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(b1);

        KeyFactory kf = KeyFactory.getInstance("RSA");

        return kf.generatePrivate(spec);

    }



    /**

     * * @param strPk PKCS8 RSA PRIVATE key

     * test result: success

     * */

    private static PrivateKey getPKCS8PrivateKey(String strPk) throws Exception {

        // Remove markers and new line characters in private key

        String realPK = strPk.replaceAll("-----END PRIVATE KEY-----", "")

                .replaceAll("-----BEGIN PRIVATE KEY-----", "")

                .replaceAll("\n", "");



        byte[] b1 = Base64.getDecoder().decode(realPK);

        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(b1);

        KeyFactory kf = KeyFactory.getInstance("RSA");

        return kf.generatePrivate(spec);

    }

}